package oss

import (
	"github.com/gin-gonic/gin"
	"jianghairui/uni-upload/appconfig"
	"jianghairui/uni-upload/utils/tools"
	"os"
	"path"
	"path/filepath"
)

type HomeController struct {
}

type FileParams struct {
	FromPath string `json:"from_path" form:"from_path" binding:"required,max=255"`
	DstPath  string `json:"dst_path" form:"dst_path" binding:"required,max=255"`
}

func (con HomeController) MoveFile(ctx *gin.Context) {
	params := FileParams{}
	err := ctx.ShouldBind(&params)
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    2,
			"message": "invalid params",
			"data":    err.Error(),
		})
		return
	}
	if params.FromPath != "" && (CheckPathPermission(params.FromPath) == false) {
		ctx.JSON(200, gin.H{
			"code":    4,
			"message": "permission denied",
			"data":    params.FromPath,
		})
		return
	}
	if params.DstPath != "" && (CheckPathPermission(params.DstPath) == false) {
		ctx.JSON(200, gin.H{
			"code":    4,
			"message": "permission denied",
			"data":    params.DstPath,
		})
		return
	}

	fileExist, _ := tools.FileExist(Prefix() + params.FromPath)
	if !fileExist {
		ctx.JSON(200, gin.H{
			"code":    1,
			"message": "file not exists",
			"data":    params.FromPath,
		})
		return
	}

	dir, _ := tools.IsDir(Prefix() + params.DstPath)
	if dir == true {
		ctx.JSON(200, gin.H{
			"code":    1,
			"message": "dst_path is dir",
			"data":    err.Error(),
		})
		return
	}

	directory := filepath.Dir(Prefix() + params.DstPath)
	err = os.MkdirAll(directory, os.FileMode(0755))
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    1,
			"message": "mkdir failed",
			"data":    err.Error(),
		})
		return
	}
	err = os.Rename(Prefix()+params.FromPath, Prefix()+params.DstPath)
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    1,
			"message": "rename error",
			"data":    err.Error(),
		})
		return
	}
	ctx.JSON(200, gin.H{
		"code":    0,
		"message": "success",
		"data":    "",
	})

}

func (con HomeController) DeleteFile(ctx *gin.Context) {
	filePath := ctx.PostForm("file_path")
	// 验证路径权限
	if filePath != "" && (CheckPathPermission(filePath) == false) {
		ctx.JSON(200, gin.H{
			"code":    4,
			"message": "permission denied",
			"data":    filePath,
		})
		return
	}
	fullPath := path.Join(Prefix(), filePath)
	err := os.Remove(fullPath)
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    1,
			"message": "delete error",
			"data":    err.Error(),
		})
		return
	}
	ctx.JSON(200, gin.H{
		"code":    0,
		"message": "success",
		"data":    "",
	})
}

func (con HomeController) UploadFile(ctx *gin.Context) {
	dstPath := ctx.PostForm("dst_path")
	file, err := ctx.FormFile("file")
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    1,
			"message": "upload error",
			"data":    err.Error(),
		})
		return
	} else {
		// 验证路径权限
		if dstPath != "" && (CheckPathPermission(dstPath) == false) {
			ctx.JSON(200, gin.H{
				"code":    4,
				"message": "permission denied",
				"data":    dstPath,
			})
			return
		}
		// 上传文件到指定的目录，在项目根路径下创建/media/upload文件夹
		filename := file.Filename
		extension := filepath.Ext(filename)
		randomName := tools.GetNano() + tools.GetRandomString(10)
		newPath := "tmp/" + randomName + extension
		if dstPath != "" {
			newPath = dstPath
		}

		dst := path.Join(Prefix(), newPath)
		dir, _ := tools.IsDir(dst)
		if dir == true {
			ctx.JSON(200, gin.H{
				"code":    1,
				"message": "dst_path is dir",
				"data":    dstPath,
			})
			return
		}

		err = ctx.SaveUploadedFile(file, dst)
		if err != nil {
			ctx.JSON(200, gin.H{
				"code":    1,
				"message": "SaveUploadedFile error",
				"data":    err.Error(),
			})
			return
		}
		//ctx.String(200, "upload success! "+filename)
		ctx.JSON(200, gin.H{
			"code":    0,
			"message": "success",
			"data": map[string]interface{}{
				"name":     filename,
				"url":      newPath,
				"full_url": AppHost + dst,
			},
		})
	}

}

func (con HomeController) FileExist(ctx *gin.Context) {
	filePath := ctx.PostForm("file_path")
	if filePath != "" && (CheckPathPermission(filePath) == false) {
		ctx.JSON(200, gin.H{
			"code":    4,
			"message": "permission denied",
			"data":    filePath,
		})
		return
	}
	fullPath := path.Join(Prefix(), filePath)
	fileExist, err := tools.FileExist(fullPath)
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    1,
			"message": "invalid param!",
			"data":    err.Error(),
		})
		return
	}
	if !fileExist {
		ctx.JSON(200, gin.H{
			"code":    1,
			"message": "not found",
			"data":    "",
		})
		return
	}
	ctx.JSON(200, gin.H{
		"code":    0,
		"message": "success",
		"data":    "",
	})

}

// Test 成功|失败的返回分别进行封装, 效果貌似不太好, 可有可无
func (con HomeController) Test(ctx *gin.Context) {
	list := make(map[string]string)
	list = appconfig.AppConfig.Section("app_key").KeysHash()
	if len(list) == 0 {
		ErrorReturn(ctx, ResponseData{Data: "", Message: "未设置密钥, 请在app.ini文件中设置!"})
		return
	}
	SuccessReturn(ctx, ResponseData{Data: map[string]interface{}{
		"list":   list,
		"prefix": Prefix(),
	}})
}

type ResponseData struct {
	Code    int
	Message string
	Data    interface{}
}

func SuccessReturn(ctx *gin.Context, respData ResponseData) {
	if respData.Message == "" {
		respData.Message = "操作成功!"
	}
	ctx.JSON(200, gin.H{
		"code":    0,
		"message": respData.Message,
		"data":    respData.Data,
	})
}

func ErrorReturn(ctx *gin.Context, respData ResponseData) {
	if respData.Message == "" {
		respData.Message = "操作失败!"
	}
	ctx.JSON(200, gin.H{
		"code":    1,
		"message": respData.Message,
		"data":    respData.Data,
	})
}
